package com.hello.sky.service.impl;

import com.hello.sky.mapper.OrderDetailMapper;
import com.hello.sky.mapper.OrdersMapper;
import com.hello.sky.mapper.UserMapper;
import com.hello.sky.model.dto.DataOverViewQueryDTO;
import com.hello.sky.model.entity.Orders;
import com.hello.sky.model.vo.*;
import com.hello.sky.service.ReportService;
import com.hello.sky.service.WorkSpaceService;
import jakarta.servlet.ServletOutputStream;
import jakarta.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cglib.core.Local;
import org.springframework.stereotype.Service;

import java.io.BufferedOutputStream;
import java.io.InputStream;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.ArrayList;
import java.util.List;
import java.util.StringJoiner;

@Service
public class ReportServiceImpl implements ReportService {

    @Autowired
    private OrdersMapper ordersMapper;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private OrderDetailMapper orderDetailMapper;
    @Autowired
    private WorkSpaceService workSpaceService;

    @Override
    public TurnoverReportVO turnoverStatistics(DataOverViewQueryDTO dto) {
        //返回数据构造
        TurnoverReportVO vo = new TurnoverReportVO();
        ArrayList<LocalDate> dateList = new ArrayList<>();
        ArrayList<Double> turnoverList = new ArrayList<>();

        //日期列表
        List<LocalDateTime> dateTimeList = getDateList(dto);

        //查询数据
        dateTimeList.forEach(date -> {
            //日期
            dateList.add(date.toLocalDate());
            //营业额
            Double amount = ordersMapper.amountBySingleDate(date.toLocalDate(), date.toLocalDate());
            turnoverList.add(amount == null ? Double.valueOf(0L) : amount);
        });

        //封装返回数据
        vo.setDateList(StringUtils.join(dateList, ","));
        vo.setTurnoverList(StringUtils.join(turnoverList, ","));
        return vo;
    }



    @Override
    public OrderReportVO ordersStatistics(DataOverViewQueryDTO dto) {
        //返回数据构造
        OrderReportVO vo = new OrderReportVO();
        //日期，以逗号分隔，例如：2022-10-01,2022-10-02,2022-10-03
        ArrayList<LocalDate> dateList = new ArrayList<>();
        //每日订单数，以逗号分隔，例如：260,210,215
        ArrayList<Integer> orderCountList = new ArrayList<>();
        //每日有效订单数，以逗号分隔，例如：20,21,10
        ArrayList<Integer> validOrderCountList = new ArrayList<>();

        //日期列表
        List<LocalDateTime> dateTimeList = getDateList(dto);
        dateTimeList.forEach(date -> {
            dateList.add(date.toLocalDate());
            Integer countDate = ordersMapper.countBySingleDate(date.toLocalDate(), date.toLocalDate());
            orderCountList.add(countDate == null ? Integer.valueOf(0) : countDate);
            Integer countDateValid = ordersMapper.countValidBySingleDate(date.toLocalDate(), date.toLocalDate(), Orders.COMPLETED);
            validOrderCountList.add(countDateValid == null ? Integer.valueOf(0) : countDateValid);
        });
        //范围内订单总数

        Integer count = ordersMapper.dateRangeAllCount(dto);
        //范围内有效订单数
        Integer countValid = ordersMapper.dateRangeValidCount(dto, Orders.COMPLETED);
        //范围内订单完成率
        Double rate = Double.valueOf(String.format("%.2f", (double)countValid / count));

        //封装返回数据
        vo.setDateList(StringUtils.join(dateList, ","));
        vo.setOrderCountList(StringUtils.join(orderCountList, ","));
        vo.setValidOrderCountList(StringUtils.join(validOrderCountList, ","));
        vo.setTotalOrderCount(count);
        vo.setValidOrderCount(countValid);
        vo.setOrderCompletionRate(rate);

        return vo;
    }

    @Override
    public UserReportVO userStatistics(DataOverViewQueryDTO dto) {
        //返回数据构造
        UserReportVO vo = new UserReportVO();
        ArrayList<LocalDate> dateList = new ArrayList<>();
        ArrayList<Integer> totalUserList = new ArrayList<>();
        ArrayList<Integer> newUserList = new ArrayList<>();

        //日期列表
        List<LocalDateTime> dateTimeList = getDateList(dto);

        //查询数据
        dateTimeList.forEach(date -> {
            //日期
            dateList.add(date.toLocalDate());
            //截至总人数
            Integer total = userMapper.countByEnd(date);
            totalUserList.add(total == null ? Integer.valueOf(0): total);
            //当日增加人数
            Integer singalDay = userMapper.countBySingleDate(date.toLocalDate(), date.toLocalDate());
            newUserList.add(singalDay == null ? Integer.valueOf(0): singalDay);
        });

        //封装返回
        vo.setDateList(StringUtils.join(dateList, ","));
        vo.setTotalUserList(StringUtils.join(totalUserList, ","));
        vo.setNewUserList(StringUtils.join(newUserList, ","));
        return vo;
    }

    @Override
    public SalesTop10ReportVO topTen(DataOverViewQueryDTO dto) {
        LocalDateTime begin = LocalDateTime.of(dto.getBegin(), LocalTime.MIN);
        LocalDateTime end = LocalDateTime.of(dto.getEnd(), LocalTime.MAX);
        return ordersMapper.topTen(begin, end);
    }

    @Override
    public void export(HttpServletResponse response) {
        LocalDate begin = LocalDate.now().minusDays(30);
        LocalDate end = LocalDate.now();
        DataOverViewQueryDTO dto = new DataOverViewQueryDTO(begin, end);
        BusinessDataVO businessDataVO = workSpaceService.businessData(dto);

        InputStream is = this.getClass().getClassLoader().getResourceAsStream("template/运营数据报表模板.xlsx");
        try {
            XSSFWorkbook excel = new XSSFWorkbook(is);
            XSSFSheet sheet = excel.getSheet("Sheet1");
            //第二行
            sheet.getRow(1).getCell(1).setCellValue(begin + "至" + end);
            //第四行
            XSSFRow row4 = sheet.getRow(3);
            row4.getCell(2).setCellValue(businessDataVO.getTurnover());
            row4.getCell(4).setCellValue(businessDataVO.getOrderCompletionRate());
            row4.getCell(6).setCellValue(businessDataVO.getNewUsers());
            //第五行
            XSSFRow row5 = sheet.getRow(4);
            row5.getCell(2).setCellValue(businessDataVO.getValidOrderCount());
            row5.getCell(4).setCellValue(businessDataVO.getUnitPrice());

            //第八行开始循环插入30次
            for (int i = 0; i < 30; i++) {
                XSSFRow row = sheet.getRow(7 + i);
                dto.setBegin(end);
                dto.setEnd(end);
                BusinessDataVO data = workSpaceService.businessData(dto);
                //日期
                row.getCell(1).setCellValue(end.toString());
                //营业额
                row.getCell(2).setCellValue(data.getTurnover());
                //有效订单
                row.getCell(3).setCellValue(data.getValidOrderCount());
                //订单完成率
                row.getCell(4).setCellValue(data.getOrderCompletionRate());
                //平均客单价
                row.getCell(5).setCellValue(data.getUnitPrice());
                //新增用户数
                row.getCell(6).setCellValue(data.getNewUsers());

                end = end.minusDays(1);
            }
            ServletOutputStream out = response.getOutputStream();
            excel.write(out);

            //关闭资源
            is.close();
            out.flush();
            out.close();
            excel.close();

        } catch (Exception e) {
            throw new RuntimeException(e);
        }

    }


    private List<LocalDateTime> getDateList(DataOverViewQueryDTO dto) {
        DataOverViewQueryDTO innerDto = new DataOverViewQueryDTO();
        BeanUtils.copyProperties(dto, innerDto);
        innerDto.setEnd(innerDto.getEnd().plusDays(1));
        ArrayList<LocalDateTime> localDateTimes = new ArrayList<>();
        while (!innerDto.getBegin().equals(innerDto.getEnd())){
            localDateTimes.add(LocalDateTime.of(innerDto.getBegin(), LocalTime.MAX));
            innerDto.setBegin(innerDto.getBegin().plusDays(1)) ;
        }
        return localDateTimes;
    }
}
